package com.hzgj.bcl.soa.util;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import lombok.Getter;

/**
 * Created by ye.pan on 2015/8/3.
 */
public class GlobalInvoke {

    private static Map<InvokeEvent, List<InvokeContext>> invokeContexts = Maps.newHashMap();
    private static Logger logger = LoggerFactory.getLogger(GlobalInvoke.class);

    public static void addContext(InvokeEvent invokeEvent, Object target, Method method, Object[] params) {
        InvokeContext invokeContext = new InvokeContext();
        invokeContext.params = params;
        invokeContext.method = method;
        invokeContext.target = target;
        invokeContexts.compute(invokeEvent, (key, contexts) -> {
            if (contexts == null) {
                contexts = Lists.newArrayList();
            }
            contexts.add(invokeContext);
            return contexts;
        });
    }

    public static void clear() {
        invokeContexts = null;
    }

    public static void invoke(InvokeEvent invokeEvent) {

        List<InvokeContext> contexts = invokeContexts.get(invokeEvent);
        if (invokeEvent instanceof ServerStartedInvokeEvent) {
            contexts.forEach(invokeContext -> {
                if (invokeContext.target != null && invokeContext.params != null) {
                    try {
                        invokeContext.method.invoke(invokeContext.target, invokeContext.params);
                    } catch (Exception e) {
                        logger.error("{}", e);
                    }
                }
            });
        }
        invokeContexts = null;
    }

    static class InvokeContext {
        public Object target;
        public Object[] params;
        public Method method;
    }

    public interface InvokeEvent {

    }

    public static class ServerStartedInvokeEvent implements InvokeEvent {
        @Getter
        private String serverId;

        public ServerStartedInvokeEvent(String serverId) {
            this.serverId = serverId;
        }

        @Override
        public boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (o == null || getClass() != o.getClass()) {
                return false;
            }
            ServerStartedInvokeEvent that = (ServerStartedInvokeEvent) o;
            return Objects.equals(serverId, that.serverId);
        }

        @Override
        public int hashCode() {
            return Objects.hash(serverId);
        }
    }
}
